from .models import QualityEvent,User,DepartMent,FlowLog,ProdRecord,FailAbstract,ProcessingScheme,FailKind,ProdModel
from helpers.director.shortcut import TablePage, ModelFields,ModelTable,page_dc,director,get_request_cache,Fields,has_permit,RowFilter,SelectSearch,RowSort,director_element
from django.utils import timezone
from django.db.models import F
from helpers.director.model_func.dictfy import to_dict
from helpers.case.jb_admin.uidict import op_excel
import json

class QualityEventPage(TablePage):
    def get_label(self):
        return '质量事件'
    
    def get_template(self, prefer=None):
        return 'jb_admin/table_new.html'
    
    class tableCls(ModelTable):
        model = QualityEvent
        exclude =[]
        fields_sort =['id','title','kind','fail_source','total_count','fail_count','status','priority' ,'prod_no','prod_model','current_department','model_no','model_name','model_spec','current_user','create_user','create_depart','create_time','printed','ops']
        # 'fail_kind',
        
        def dict_head(self, head):
            if head['name']=='title':
                head['after_fields']=['printed']
            return head
        
        def get_operations(self):
            ops = super().get_operations()
            out =[]
            for op in ops:
                if op['name'] =='add_new' and has_permit(self.crt_user,'event.create'):
                    op['click_express'] =''' scope.head.fields_ctx.genVc=scope.vc;scope.ps.add_new(scope.head).then(resp=>{
                    var par_row = ex.findone(scope.ps.rows,{pk:resp.pk})
                    scope.ps.switch_to_tab({ctx_name:'quality-event-tabs',tab_name:'flow-tab',par_row:par_row})
                    })'''
                    out.append(op)
            out += [
                op_excel(),
                {'name':'print','label':'打印',
                 'editor':'com-btn',
                 'row_match':"one_row",
                 'click_express':'''
                 async function doit(){
                     if(!scope.ps.selected[0].printed){
                         scope.ps.selected[0].printed=true
                         cfg.show_load()
                         await ex.director_call("d.save_row",{row:scope.ps.selected[0]})
                         cfg.hide_load()
                     }
                     window.open(`/pc/print_event?id=${scope.ps.selected[0].pk}`) 
                 }
                 doit()
                 '''},
            ]
            return out
        
        def inn_filter(self, query):
            return query.annotate(current_department =F('current_user__userinfo__department__name'),
                                  create_department=F('create_user__userinfo__department__name') )
        
        def get_head_context(self):
            ctx = super().get_head_context()
            # 质量部门领导可以关闭
            department = DepartMent.objects.get(pk=1000)
            can_close = self.crt_user in department.leader.all()
            if not can_close:
                # 总经办领导也可以关闭
                department = DepartMent.objects.get(pk=1)
                can_close = self.crt_user in department.leader.all()
            get_request_cache()['named_ctx'].update({
                'quality-event-tabs':[
                    {'name':'flow-tab',
                    'label':'小单',
                     'editor':'quality-flow',
                     'button_can_close':can_close,
                     "my_user_id":self.crt_user.pk,
                     'can_create':has_permit(self.crt_user,'event.create'),
                     'can_edit_tech':has_permit(self.crt_user,'event.tech.edit'),
                     'can_edit_fail_content':has_permit(self.crt_user,'event.fail_content.edit'),
                     'can_edit_validate':has_permit(self.crt_user,'event.validate.edit'),
                     'can_edit_approval':has_permit(self.crt_user,'event.approval.edit'),
                     'user_department':self.crt_user.userinfo.department_id,
                     },
                    #{'name':'flow-tabaa',
                    #'label':'嘉的',
                     #'editor':'quality-flow',
                        #}
                ]
            })
            get_request_cache()['named_ctx'].update({
                'quliaty_event_base_form':QualityEventForm().get_head_context(),
                # 关闭技术工艺
                #'quliaty_event_processing_form':ProcessingForm().get_head_context(),
                'quality_event_validata_form':ValidatingForm().get_head_context(),
                'quality_event_approval_form':ApprovalForm().get_head_context(),
                
                'quality.flow.edit':FlowForm().get_head_context(),
                'quality.flow.finish':FinishForm().get_head_context(),
                'quality.flow.agree':AgreeForm().get_head_context(),
                'quality.flow.close':CloseForm().get_head_context(),
                'quality.fail_content_ctx':{
                    'abstract_options':[{'value':x.pk,'label':str(x)} for x in FailAbstract.objects.all()],
                    'process_schem_options':[{'value':x.pk,'label':str(x)} for x in ProcessingScheme.objects.all()],
                    'fail_kind_options':[{'value':x.pk,'label':str(x)} for x in FailKind.objects.all()]
                },
                'quality.flow.trans_zhong':TransToZhongForm().get_head_context(),
                'ProdModelPicker':ProdModelPicker().get_head_context()
            })
            
            return ctx
        
        def getExtraHead(self):
            return [
                {'name':'current_department','label':'当前部门',},
                
                {'name':'ops','label':'操作','editor':'com-table-ops-cell','fixed':'right',
                            'ops':[
                                 {'editor':'com-btn', 
                                  'label':'详情',
                                  'width':100,
                                #'icon':'el-icon-phone',
                                #'fa_icon':'fa fa-phone-square',
                                'type':'primary',
                                #'shape':'circle',
                                
                                #'css':'.myphone button{ padding: 2px;}',
                                #'class':'myphone',
                                'click_express':"scope.ps.vc.parStore.switch_to_tab({ctx_name:'quality-event-tabs',tab_name:'flow-tab',par_row:scope.ps.vc.rowData})"}
                            ]}                
            ]
        
        def dict_row(self, inst):
            if(inst.fail_ratio>0.03 or inst.fail_count > 50):
                need_zhong_agree = True
            else:
                need_zhong_agree = False
            return {
                'current_department':inst.current_department,
                'create_department':inst.create_department,
                '_need_zhong_agree':need_zhong_agree,
                'can_edit_solution':self.crt_user.userinfo.department_id == 3, # 技术部门
                '_user_can_direct_close': has_permit(self.crt_user,'can_direct_close_event')
            }
        
        def getExcelHead(self):
            heads = self.get_heads()  
            heads +=[
                {'name':'fail_content__abstract','label':'不合格内容'},
                {'name':'fail_content__count','label':'数量'}
            ]
           
            return heads
        
        
        def getExcelRows(self):
            rows = self.get_rows()  
            fail_map = {x.pk:x.desp for x in FailAbstract.objects.all()}
            out_rows =[]
            for row in rows:
                if row.get('fail_content'):
                    events = json.loads(row.get('fail_content'))
                    for ii in events:
                        dc = dict(row)
                        dc['fail_content__abstract'] = fail_map.get( ii['abstract'] )
                        dc['fail_content__count'] = int(ii['count'])
                        out_rows.append(dc)
                else:
                    out_rows.append(row)
            return out_rows
        
        #def after_excel(self, wb, ws, out_rows):
            #for index,v in enumerate(out_rows):
                #ws.cell(index+2,)
                #ws['T%s'%(index+2)].number_format = '0'
                
        class filters(RowFilter):
            names =['kind','fail_source','status','current_depart','create_depart','printed']
            range_fields=['create_time']
        #class search(SelectSearch):
            #names = ['fail_source__name']
            #label_map = {'fail_source__name':'不合格来源'}
            
        class sort(RowSort):
            names =['create_time','total_count','fail_count']

class QualityEventForm(ModelFields):
    outdate_check_fields = []
    
    field_sort = ['title','kind',
                  'prod_record','prod_no','prod_model','fail_count','model_spec','model_no','model_name',
                  'customer_info','quit_number','supplyer_info','receive_number',
                  'total_count','fail_ratio','prod_part','fail_source','fail_kind',
                 'priority','status','fail_memo']
    class Meta:
        model = QualityEvent
        exclude = []
    
    def clean_dict(self, dc):
        if dc.get('total_count') and float( dc.get('total_count') )!=0 :
            dc['fail_ratio'] = round( float( dc.get('fail_count') )  / float( dc.get('total_count') ),2)
        else:
            dc['fail_ratio'] = 0
        return dc
    
    def clean_save(self):
        if self.is_create:
            self.instance.create_user = self.crt_user
            self.instance.current_user = self.crt_user
            self.instance.create_depart = self.crt_user.userinfo.department
            
        if self.kw.get('meta_op')=='processing':
            self.instance.process_worker = self.crt_user
            self.instance.process_datetime = timezone.now()
        if self.kw.get('meta_op') == 'validating':
            self.instance.validate_worker = self.crt_user
            self.instance.validate_datetime = timezone.now()
        if self.kw.get('meta_op') =='approval':
            self.instance.approval_worker = self.crt_user
            self.instance.approval_datetime = timezone.now()
        
    
    def dict_head(self, head):
        if head['name']=='fail_memo':
            head['colspan']=3
            head['class']='my-block-1'
            head['css']='''.my-block-1 textarea{min-width:400px;min-heigth:100px}
            '''
        if head['name'] =='prod_record':
            head['required'] = True
            head['show_express']='ex.isin(scope.row.kind,[1,5])' #  1过程不合格 和 成品不合格 都需要去选择
            head['editor'] = 'com-field-pop-table-select'
            head['options'] =[]
            head['table_ctx'] = ProdRecordTable().get_head_context()
            head['after_select_express']='''
            scope.row.prod_no=scope.selected_row.no
            scope.row.model_no=scope.selected_row.model_no
            scope.row.model_name=scope.selected_row.model_name
            scope.row.total_count=scope.selected_row.count
            scope.row.model_spec=scope.selected_row.model_spec'''
        if head['name'] =='prod_no':
            head['show_express']='! ex.isin(scope.row.kind,[1,5])' #生平批号 1 和成品5都是选的
            head['required_express'] = '!ex.isin(scope.row.kind,[2,3,4]) ' # 客诉的时候，生产批号不是必填; 供应商时不必填
        
        if head['name']=='model_name':
            head['editor'] = 'com-field-pop-table-select'
            head['options'] =[]
            head['table_ctx']= ProdModelPicker().get_head_context()
            head['type_input']=True
            head['after_select_express']='''
            scope.row.model_no=scope.selected_row.no;
            scope.row.model_name=scope.selected_row.name;
            scope.row.model_spec=scope.selected_row.specification
            '''
            
        if head['name'] in ['model_spec','total_count','model_no','model_name']:
            head['readonly_express']='ex.isin(scope.row.kind,[1,5])'
        if head['name'] =='fail_memo':
            head['width'] ='500px'
        if head['name']=='model_no':
            head['required_express'] = 'scope.row.kind ==2' # 客诉的时候，品号必填
        #if head['name']=='receive_number': # 只有供应商在用，现在不要求必填
            #head['required']=True
        return head
    
    def get_head_context(self):
        ctx = super().get_head_context()
        ctx.update({
            'width':'700px',
            'title':'基本信息',
            'table_grid':[
                ['title','kind'],
                ['prod_record','prod_no'],
                ['customer_info','quit_number','supplyer_info','receive_number'],
                
                ['model_spec','total_count',],
                ['model_no','model_name',],
                ['priority','fail_source'],
                ['fail_count']
               ],  
            'fields_group':[
                {'name':'huji','label':'头信息','heads':['title','kind']},
                {'name':'info1','label':'客诉信息','heads':['customer_info','quit_number'],
                 'show_express':'scope.row.kind==2'},
                {'name':'info2','label':'供应商信息','heads':['supplyer_info','receive_number'],
                 'show_express':'scope.row.kind==3'},
                {'name':'bb','label':'生产信息','heads':['prod_record','prod_no','model_spec','total_count','model_no','model_name']},
                {'name':'subinfo','label':'上报信息','heads':['priority','fail_source','fail_count']} #,,'fail_kind','fail_memo'
             ],            
        })
        return ctx

class ProdRecordTable(ModelTable):
    model = ProdRecord
    #exclude = []
    include = ['no','main_part_code','main_part_name','main_part_spec','count']
    selectable = False
    
    def getExtraHead(self):
        return [
            {'name':'op','editor':'com-table-button-click',
             'label':'操作',
             'button_label':'选择',
             'click_express':"scope.ps.$emit('finish',scope.row)"}
        ]
    
    def inn_filter(self, query):
        return query.annotate(model_no = F('model__no'),
                              model_name=F('model__name'),
                              model_spec=F('model__specification'))
    
    def dict_head(self, head):
        if head['name'] =='id':
            head['editor']='com-table-foreign-click-select'
        return head
    
    def dict_row(self, inst):
        return {
            'model_no':inst.model_no,
            'model_name':inst.model_name,
            'model_spec':inst.model_spec
        }
    
    class filters(RowFilter):
        names =['no',]
        icontains=['no',]
        #def getExtraHead(self):
            #return [
                #{'name':'model__name','label':'品名'}
            #]

class ProcessingForm(ModelFields):
    class Meta:
        model = QualityEvent
        fields =['processing_scheme','tech_suggest','craft_suggest','tech_correct_action','craft_correct_action']
    field_sort =['processing_scheme','tech_suggest','tech_correct_action','craft_suggest','craft_correct_action']
    def get_head_context(self):
        ctx = super().get_head_context()
        ctx.update({
            'title':'技术工艺',
            'width':'720px',
        })
        return ctx


class ValidatingForm(ModelFields):
    class Meta:
        model = QualityEvent
        fields =['validate_action',]
        
    def get_head_context(self):
        ctx = super().get_head_context()
        ctx.update({
            'title':'质量验证',
            'width':'720px',
            'height':'300px',
        })
        return ctx

class ApprovalForm(ModelFields):
    class Meta:
        model = QualityEvent
        fields =['approval_suggest',]   
        
    def get_head_context(self):
        ctx = super().get_head_context()
        ctx.update({
            'title':'总经办审批',
            'width':'720px',
            'height':'300px',
        })
        return ctx

class FlowForm(Fields):
    "处理流转操作"
    def get_head_context(self):
        ctx = super().get_head_context()
        ctx.update({
            'title':'流转信息',
            'width':'720px',
            'height':'300px',
        })
        return ctx
    
    def get_heads(self):
        options = []        
        department = self.crt_user.userinfo.department
        if department:
            # 本部门负责人
            this_dep_leaders = []
            for inst in department.leader.all():
                this_dep_leaders.append(inst)
                if inst != self.crt_user:
                    options.append(
                        {'value':inst.pk,'label':'%s(本部负责人)'%inst.first_name}
                    )
            # 部门内部人员
            for inst in User.objects.filter(userinfo__department = department):
                if self.crt_user!= inst and inst not in this_dep_leaders:
                    options.append({'value':inst.pk,'label':'%s'%inst.first_name})
            #if self.crt_user in this_dep_leaders:
                #leaders = []
                #for inst in department.leader.all():
                    #leaders.append(inst)
                    #if self.crt_user!= inst:
                        #options.append({'value':inst.pk,'label':'%s(负责人)'%inst.first_name})
            
                
            if self.crt_user in this_dep_leaders:
                for inst in User.objects.filter(department_leader__isnull=False).distinct():
                    if inst not in this_dep_leaders:
                        options.append({'value':inst.pk,'label':'%s(负责人)'%inst.first_name})

        
        return [
            {'name':'recieve_user','label':'接收人','editor':'com-field-select','options':options,'required':True},
            {'name':'memo','label':'备注','editor':'com-field-blocktext',},
        ]
    
    def save_form(self):
        current_user = User.objects.get(pk= self.kw.get('recieve_user'))
        QualityEvent.objects.filter(id=self.kw.get('quality_event')).update(
            current_user= current_user,
            current_depart = current_user.userinfo.department,
            status=2 
        )
        FlowLog.objects.create(user=self.crt_user,
                               event_id=self.kw.get('quality_event'),
                               target_id=self.kw.get('recieve_user'),
                               memo = self.kw.get('memo',''))
    
    def dict_row(self):
        if self.kw.get('quality_event'):
            ff = QualityEventForm(pk=self.kw.get('quality_event'))
            return ff.get_row()
        else:
            return {}

class TransToZhongForm(Fields):
    def get_head_context(self):
        ctx = super().get_head_context()
        ctx.update({
            'title':'转总经办',
            'width':'720px',
            'height':'300px',
        })
        return ctx
    
    def get_heads(self):
        options = []
        zhong_department = DepartMent.objects.get(pk=1)
        zhong_leaders = zhong_department.leader.all()
        for inst in User.objects.filter(userinfo__department_id = 1):
            if inst in zhong_leaders:
                options.append({'value':inst.pk,'label':str(inst)})
        return [
            {'name':'recieve_user','label':'接收人','editor':'com-field-select','options':options,'required':True},
            #{'name':'memo','label':'备注','editor':'com-field-blocktext',},
        ]
    
    def save_form(self):
        current_user = User.objects.get(pk= self.kw.get('recieve_user'))
        QualityEvent.objects.filter(id=self.kw.get('quality_event')).update(
            current_user= current_user,
            current_depart_id = 1 , # current_user.userinfo.department,
            status=6 
        )
        FlowLog.objects.create(user=self.crt_user,
                               event_id=self.kw.get('quality_event'),
                               target_id=self.kw.get('recieve_user'),
                               memo = '转总经办')
        

class FinishForm(Fields):
    """结件  2->3"""
    def get_head_context(self):
        ctx = super().get_head_context()
        ctx.update({
            'title':'结件',
            'width':'720px',
            'height':'300px',
        })
        return ctx
    
    def get_heads(self):
        return [
            {'name':'memo','label':'备注','editor':'com-field-blocktext',},
        ]
    
    def save_form(self):
        inst = QualityEvent.objects.get(pk = self.kw.get('quality_event'))
        if inst.status==2:
            inst.status=3
            inst.current_user = inst.create_user
            inst.current_depart = inst.create_user.userinfo.department
            inst.save()
            FlowLog.objects.create(user=self.crt_user,
                                   event=inst,
                                   kind = 2,
                                   target= inst.create_user,
                                   memo = self.kw.get('memo',''))            
        else:
            raise UserWarning('只有处理中的事件才能结件!')


class AgreeForm(FlowForm):
    """创建人同意，转质量部门  3->4"""
    def get_heads(self):
        options = []    
        department = DepartMent.objects.get(pk= 1000)

        if department:
            # 本部门负责人
            this_dep_leaders = []
            for inst in department.leader.all():
                this_dep_leaders.append(inst)
                if inst != self.crt_user:
                    options.append(
                        {'value':inst.pk,'label':'%s(质量负责人)'%inst.first_name}
                    )

        return [
            {'name':'recieve_user','label':'接收人','editor':'com-field-select','options':options,'required':True},
            {'name':'memo','label':'备注','editor':'com-field-blocktext'},
        ]
    
    def save_form(self):
        inst = QualityEvent.objects.get(pk = self.kw.get('quality_event'))
        target_user = User.objects.get(pk = self.kw.get('recieve_user') )
        if inst.status==3:
            inst.status=4
            inst.current_user = target_user
            inst.current_depart =  target_user.userinfo.department
            inst.save()
            FlowLog.objects.create(user=self.crt_user,
                                   event=inst,
                                   kind = 3,
                                   target_id = self.kw.get('recieve_user'),
                                   memo = self.kw.get('memo',''))            
        else:
            raise UserWarning('只有结件中的事件才能同意操作!')


 

class CloseForm(FinishForm):
    """4->5 质量部门关闭；  6->5 总经办关闭 """
    def save_form(self):
        inst = QualityEvent.objects.get(pk = self.kw.get('quality_event'))
        #if inst.status in [4,6]:
        inst.status=5
        inst.save()
        FlowLog.objects.create(user=self.crt_user,
                               event=inst,
                               kind = 4,
                               target= inst.create_user,
                               memo = self.kw.get('memo',''))            
        #else:
            #raise UserWarning('只有处理中的事件才能关闭!')    

@director_element('prodmodel-picker')
class ProdModelPicker(ModelTable):
    model = ProdModel
    exclude =[]
    
    def dict_head(self, head):
        if head['name'] =='no':
            head.update({
                'editor':'com-table-click',
                'click_express':"scope.ps.$emit('finish',scope.row)",     
            })
        return head
    
    class search(SelectSearch):
        names = ['no','name','specification']
       

class TodoEvent(TablePage):
    def get_label(self):
        return '待办事件'
    def get_template(self, prefer=None):
        return 'jb_admin/table_new.html'
    
    class tableCls(QualityEventPage.tableCls):
        nolimit = True
        def get_operations(self):
            return []
        
        def inn_filter(self, query):
            query = super().inn_filter(query)
            return query.filter(current_user=self.crt_user,).exclude(status=5)


class TodoEventForm(QualityEventForm):
    nolimit = True

director.update({
    'quality':QualityEventPage.tableCls,
    'quality.edit':QualityEventForm,
    'quality.processing.edit':ProcessingForm,
    'quality.validate.form':ValidatingForm,
    'quality.approval.edit':ApprovalForm,
    
    'quality.flow.edit':FlowForm,
    'quality.flow.finish':FinishForm,
    'quality.flow.agree':AgreeForm,
    'quality.flow.close':CloseForm,
    'quality.flow.trans_zhong':TransToZhongForm,
    
    'quality.prodrecord':ProdRecordTable,
    
    'todo_event':TodoEvent.tableCls,
    'todo_event.edit':TodoEventForm,
    
})
    
page_dc.update({
    'quality':QualityEventPage,
    'todo_event':TodoEvent
})